---
title: Tool specification
---

import HeaderLabel from '@site/src/components/Docs/HeaderLabel';
import VersionLabel from '@site/src/components/Docs/VersionLabel';

<HeaderLabel text="3 min" />

Since proto is a toolchain for multiple tools, each with differing version formats, we must align
them on a standard specification that can resolve and store safely. To handle this, we've
implemented our own solution called the tool and version specification. This specification currently
supports semantic and calendar based versions, each with their own guidelines and caveats.

:::info

If you're implementing a plugin for a specific tool that has a different version format, you'll need
to re-format it into one of the specifications below.

:::

## Backends<VersionLabel version="0.47.0" />

A backend is an internal system that allows proto to use plugins from 3rd-party package/version
managers within proto, greatly expanding the amount of tools that proto can install and support.
This functionality is achieved through special WASM plugins under the hood.

To make use of a backend, prefix the tool identifier in `.prototools` with the backend's unique
identifier. For example, we can install Zig via asdf.

```toml title=".prototools"
# >= v0.52
"asdf:zig" = "0.13.0"

# <= v0.51
zig = "asdf:0.13.0"
```

### `asdf`

The `asdf` backend will utilize the [asdf version manager](https://asdf-vm.com/) for downloading and
installing a tool, loading versions, and locating executables. This backend implementation _does
not_ use the `asdf` binary itself, and instead emulates the environment as best we can. Because of
this, some tools may not be usable through proto.

```toml title=".prototools"
"asdf:<id>" = "20"
```

By default, the ID pinned in `.prototools` is the
[asdf shortname](https://asdf-vm.com/plugins/create.html#plugin-shortname-index) used when cloning a
repository. If the ID is different than the shortname (`node` vs `nodejs`), you can configure the
`asdf-shortname` setting.

```toml title=".prototools"
"asdf:node" = "20"

[tools."asdf.node"]
asdf-shortname = "nodejs"
```

The following settings are supported:

- `asdf-shortname` (string) - The name of the [asdf plugin](https://github.com/asdf-vm/asdf-plugins)
  if different than the configured ID.
- `asdf-repository` (string) - The Git repository URL in which to locate
  [scripts](https://asdf-vm.com/plugins/create.html#scripts-overview). If not defined, is extracted
  from the shortname plugin index.
- `exes` (string[]) - List of executable file names (relative from `bin`) to be linked as a
  shim/bin. If not defined, we'll automatically scan the `bin` directory.

## Semantic versions

The most common format is [semver](https://semver.org/), also known as a semantic version. This
format requires major, minor, and patch numbers, with optional pre-release and build metadata.

```toml title=".prototools"
tool = "1.2.3"
```

### Syntax

- `<major>.<minor>.<patch>` - 1.2.3
- `<major>.<minor>.<patch>-<pre>` - 1.2.3-alpha.0
- `<major>.<minor>.<patch>-<pre>+<build>` - 1.2.3-alpha.0+nightly456
- `<major>.<minor>.<patch>+<build>` - 1.2.3+nightly456

### Guidelines

- major, minor, patch - `0-9` of any length
- pre, build - `a-z`, `0-9`, `-`, `.`

> [Learn more about this format!](https://semver.org/#backusnaur-form-grammar-for-valid-semver-versions)

## Calendar versions<VersionLabel version="0.37.0" />

Another popular format is [calver](https://calver.org/), also known as a calendar version, which
uses the calendar year, month, and day as version numbers. This format also supports pre-release and
build metadata, but with different syntax than semver.

```toml title=".prototools"
tool = "2025-02-26"
```

### Syntax

- `<year>-<month>` - 2024-02
- `<year>-<month>-<day>` - 2024-02-26
- `<year>-<month>-<day>.<build>` - 2024-02-26.123
- `<year>-<month>-<day>_<build>` - 2024-02-26_123
- `<year>-<month>-<day>.<build>-<pre>` - 2024-02-26.123-alpha.0
- `<year>-<month>-<day>_<build>-<pre>` - 2024-02-26_123-alpha.0
- `<year>-<month>-<day>-<pre>` - 2024-02-26-alpha.0

### Guidelines

- year - `0-9` of 1-4 length
  - If the year is not YYYY format, it will use the year 2000 as the base. For example, `24` becomes
    `2024`, and `124` becomes `2124`.
- month - `0-9` of 1-2 length
  - Supports with and without a leading zero (`02` vs `2`).
  - Does not support invalid months (`0` or `13`).
- day - `0-9` of 1-2 length
  - Can be omitted, even with build/pre.
  - Supports with and without a leading zero (`02` vs `2`).
  - Does not support invalid days (`0` or `32`).
- build - `0-9` of any length
  - Also known as a "micro" number.
  - The leading dot `.` format is preferred.
- pre - `a-z`, `0-9`, `-`, `.`

> [Learn more about this format!](https://calver.org/#scheme)

## Requirements and ranges

Besides an explicit version, we also support partial versions known as version requirements or
version ranges. These are quite complex as we need to support both semver and calver in unison, as
well as support partial/incomplete numbers (missing patch/day, missing minor/month, etc). We do our
best to support as many combinations as possible.

```toml title=".prototools"
tool-a = "^1"
tool-b = "~2.1"
tool-c = ">=2000-10"
```

### Syntax

- Requirement - `[<op>]<pattern>` - `1.2.3`, `>4.5`, `~3`, `^2000-10`, etc
- AND range - `<requirement>[,] <requirement> ...` - `>=1, <2`, `^1.3 <=1.3.9`, etc
- OR range - `<requirement> || <requirement> ...` - `^1.2 || ^2.3`, `~2000-10 || ~2010-2`, etc

### Guidelines

- op - `=`, `>`, `>=`, `<=`, `<`, `~`, `^`
  - If omitted, defaults to `~` when a partial version is provided (i.e. allow the minimum specified version component to increase)
  - If a full version is provided, defaults to `^` (i.e. allow any newer version that is nominally compatible)
  - To specify an *exact* version, use the `=` operator explicitly.
- pattern
  - Dot-separated semver, with optional major and patch numbers.
  - Dash-separated calver, with optional month and day numbers.
  - Pre-release and build metadata are only supported when suffixed to full versions.

For example, if you want to use `npm` 11.6.2 but 11.6.3 has an issue, use: `npm = "^11.6.4 || =11.6.2"`
